package com.example.mymessagequeue.mqserver.core;

import java.io.Serializable;
import java.util.Arrays;
import java.util.UUID;

/**
 * 一条要传递的消息
 * Message 能够在网络上传输, 也需要写入到文件中, 所以 Message 要支持序列化和反序列化
 * 此处不适用 json, 因为 json 本质上是文本格式, 而 Message 里面存储的是 二进制 数据, 所以这里使用标准库自带的序列化
 */
public class Message implements Serializable {

    private static final long serialVersionUID = 1L;

    // 属性
    private BasicProperties basicProperties = new BasicProperties();

    //内容
    private byte[] body;

    // 下面是辅助作用的属性

    // Message 会存储到文件中(持久化的话)
    // 一个文件中将会存储很多的消息, 确保找到某个消息在文件中的具体位置, 使用下面的两个偏移量
    // [offsetBeg, offsetEnd)
    // 这两个属性不需要被序列化, 因为消息一旦被写入文件之后, 所在的位置就固定了, 并不需要单独存储.
    // 这两个属性的目的, 主要就是为了让内存中的 Message 对象, 能够快速找到对应硬盘上的 Message 的位置.
    private transient long offsetBeg = 0;  // 消息数据开头距离文件开头位置(字节)
    private transient long offsetEnd = 0;  // 消息数据结尾距离文件开头位置(字节)

    // 表示这个消息在文件中是否有效. (逻辑删除, 针对文件中的消息)
    private byte isValid = 0x1;  // 0x1 有效, 0x0 无效

    // 工厂方法
    // 创建的 Message 对象, 会自动生成唯一的 MessageId
    public static Message createMessageWithId(String routingKey, BasicProperties basicProperties, byte[] body) {
        Message message = new Message();
        if (basicProperties != null) {
            message.setBasicProperties(basicProperties);
        }
        message.setMessageId("M-" + UUID.randomUUID());
        // 如果 routingKey 和 basicProperties 里面的 routingKey 相同, 以传递的为主
        message.setRoutingKey(routingKey);
        message.setBody(body);

        // offsetBeg offsetEnd isValid 持久化时需要用到, 此处只是在内存中创建一个 Message 对象
        return message;
    }

    public String getMessageId() {
        return basicProperties.getMessageId();
    }

    public void setMessageId(String messageId) {
        basicProperties.setMessageId(messageId);
    }

    public String getRoutingKey() {
        return basicProperties.getRoutingKey();
    }

    public void setRoutingKey(String routingKey) {
        basicProperties.setRoutingKey(routingKey);
    }

    public int getDeliverMode() {
        return basicProperties.getDeliverMode();
    }

    public void setDeliverMode(int mode) {
        basicProperties.setDeliverMode(mode);
    }

    public BasicProperties getBasicProperties() {
        return basicProperties;
    }

    public void setBasicProperties(BasicProperties basicProperties) {
        this.basicProperties = basicProperties;
    }

    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    public long getOffsetBeg() {
        return offsetBeg;
    }

    public void setOffsetBeg(long offsetBeg) {
        this.offsetBeg = offsetBeg;
    }

    public long getOffsetEnd() {
        return offsetEnd;
    }

    public void setOffsetEnd(long offsetEnd) {
        this.offsetEnd = offsetEnd;
    }

    public byte getIsValid() {
        return isValid;
    }

    public void setIsValid(byte isValid) {
        this.isValid = isValid;
    }

    @Override
    public String toString() {
        return "Message{" +
                "basicProperties=" + basicProperties +
                ", body=" + Arrays.toString(body) +
                ", offsetBeg=" + offsetBeg +
                ", offsetEnd=" + offsetEnd +
                ", isValid=" + isValid +
                '}';
    }
}
